// 使用内置的URL对象解析URL字符串

function parseURL1(url) {
  // 构造一个URL对象
  try {
    const urlObj = new URL(url);
    return {
      protocol: urlObj.protocol,
      host: urlObj.host,
      hostname: urlObj.hostname,
      port: urlObj.port,
      pathname: urlObj.pathname,
      search: urlObj.search,
      hash: urlObj.hash
    };
  } catch(error) {
    throw new Error('Invalid URL');
  }
}


// 手动解析URL字符串
function parseURL2(url) {
  // 定义正则表达式
  const parser = /^(https?:)\/\/([^:/]+)(:\d+)?(\/[^?#]*)?(\?[^#]*)?(#.*)?$/;
  // 使用正则表达式解析URL字符串
  const matches = url.match(parser);
  return {
    protocol: matches[1],       // 协议
    host: matches[2],           // 主机名
    port: matches[3] ? matches[3].substring(1) : '', // 端口
    pathname: matches[4] || '/',// 路径
    search: matches[5] || '',   // 查询字符串
    hash: matches[6] || ''      // 锚点
  };
}

// 测试
const url = 'https://example.com:8080/path/to/page?name=John&age=30#section';
console.log(parseURL1(url));
console.log(parseURL2(url));

/*
这个正则表达式 `^(https?:)\/\/([^:/]+)(:\d+)?(\/[^?#]*)?(\?[^#]*)?(#.*)?$` 用于解析 URL。我们可以将其分解成不同的部分进行解释：

### 1. `^` 和 `$`：匹配开始和结束位置
- `^`：表示字符串的开头。
- `$`：表示字符串的结尾。
- 整个正则表达式从 URL 的开始匹配到结束，确保我们匹配的是完整的 URL。

### 2. `(https?:)`：协议部分
- `https?`：匹配 `http` 或 `https`。`s?` 表示字符 `s` 是可选的，意味着可以是 `http` 或 `https`。
- `()`：将 `https?` 包裹起来，表示一个捕获组。这个捕获组的内容会被提取出来，方便后续使用。
- `:`：匹配协议部分的冒号，如 `http:` 或 `https:`。

### 3. `\/\/`：双斜杠
- 这是字面匹配 `//`，对应 URL 中 `http://` 或 `https://` 这样的双斜杠。因为 `/` 是正则表达式中的特殊字符，所以需要使用 `\\` 来转义。

### 4. `([^:/]+)`：主机名部分
- `[^:/]`：这是一个字符集，匹配任意不包含 `:` 和 `/` 的字符。`^` 在字符集中表示取反，即不匹配 `:` 和 `/`。
- `+`：表示匹配前面的字符集一次或多次，即至少要有一个字符。
- `()`：捕获组，用于提取主机名部分。

#### 示例：
- 如果 URL 是 `https://example.com:8080/path`, 那么 `example.com` 将被捕获。

### 5. `(:\d+)?`：端口号部分
- `:`：字面匹配冒号，表示端口号的前缀。
- `\d+`：匹配一个或多个数字，即端口号。`\d` 代表数字字符，`+` 表示匹配一次或多次。
- `()?`：捕获组和 `?` 组合在一起表示端口号是可选的。如果没有指定端口号，则不会捕获此部分。

#### 示例：
- `:8080` 会被匹配为端口号 `8080`。

### 6. `(\/[^?#]*)?`：路径部分
- `\/`：字面匹配 `/`，表示路径部分的开始。
- `[^?#]*`：匹配任意不包含 `?` 和 `#` 的字符序列（即路径部分中的字符）。`*` 表示可以匹配零个或多个字符。
- `()?`：整个路径部分是可选的，如果没有路径部分，这一部分不会捕获。

#### 示例：
- `/path/to/page` 被捕获为路径部分。

### 7. `(\?[^#]*)?`：查询字符串部分
- `\?`：字面匹配 `?`，表示查询字符串的开始。
- `[^#]*`：匹配任意不包含 `#` 的字符序列（查询字符串的内容）。
- `()?`：查询字符串是可选的。

#### 示例：
- `?name=John&age=30` 会被捕获为查询字符串。

### 8. `(#.*)?`：锚点部分
- `#`：字面匹配 `#`，表示 URL 中的锚点部分。
- `.*`：匹配任意字符序列（锚点部分的内容）。`*` 表示可以匹配零个或多个字符。
- `()?`：整个锚点部分是可选的。

#### 示例：
- `#section` 会被捕获为锚点部分。

---

### 整体结构

- `^(https?:)\/\/([^:/]+)(:\d+)?(\/[^?#]*)?(\?[^#]*)?(#.*)?$`
  - `^` 和 `$`：匹配整个 URL 的开头和结尾。
  - `(https?:)`：匹配 `http` 或 `https` 协议。
  - `\/\/`：匹配双斜杠 `//`。
  - `([^:/]+)`：匹配主机名。
  - `(:\d+)?`：匹配端口号（可选）。
  - `(\/[^?#]*)?`：匹配路径部分（可选）。
  - `(\?[^#]*)?`：匹配查询字符串（可选）。
  - `(#.*)?`：匹配锚点部分（可选）。

---
*/ 